// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import * as xml2js from 'xml2js';

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {

	// Use the console to output diagnostic information (console.log) and errors (console.error)
	// This line of code will only be executed once when your extension is activated
	console.log('Congratulations, your extension "debug-for-netcore" is now active!');

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with registerCommand
	// The commandId parameter must match the command field in package.json
	const disposable = vscode.commands.registerCommand('debug-for-netcore.helloWorld', () => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		vscode.window.showInformationMessage('Hello World from debug for netcore!');
	});

	context.subscriptions.push(disposable);

	console.log('register debug config..........');

	// 注册调试配置
	let netcoredbgConfig = vscode.debug.registerDebugConfigurationProvider('coreclr', {
		async provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined): Promise<vscode.DebugConfiguration[]> {
			try {
				if (!folder?.uri?.fsPath) {
					return [];
				}
				// 获取 folder.uri.fsPath 下的所有文件夹中的 csproj 文件
				let folders = await fs.promises.readdir(folder.uri.fsPath, { withFileTypes: true });
				folders = folders.filter(folder => folder.isDirectory());
				const runableProj = await Promise.all(folders.map(async folderPath => {
					let files = await fs.promises.readdir(path.join(folderPath.parentPath, folderPath.name), { withFileTypes: true });
					files = files.filter(file => file.isFile() && file.name.endsWith('.csproj'));
					if (files.length > 0) {
						return {
							filePath: path.join(folderPath.parentPath, folderPath.name, files[0].name),
							projectName: folderPath.name,
							projectPath: path.join(folderPath.parentPath, folderPath.name)
						};
					}
				}));
				const csprojs = runableProj.filter(uri => uri !== undefined && uri !== null);
				if (csprojs.length === 0) {
					vscode.window.showErrorMessage('未找到任何可启动项目');
					return [];
				}

				const items = await Promise.all(csprojs.map(async uri => {
					const content = await fs.promises.readFile(uri.filePath, 'utf-8');
					const xml = await xml2js.parseStringPromise(content);
					if (!xml?.Project) {
						return [];
					}
					const sdk = xml.Project.$["Sdk"];
					const propertyGroups = xml.Project.PropertyGroup;

					if (!propertyGroups || propertyGroups.length === 0) {
						return [];
					}

					let outputType = '';
					let targetFramework = '';
					let outputPath = '';
					propertyGroups.forEach((propertyGroup: any) => {
						if (propertyGroup["OutputType"] && propertyGroup["OutputType"].length > 0) {
							outputType = propertyGroup["OutputType"][propertyGroup["OutputType"].length - 1];
						}
						if (propertyGroup["TargetFramework"] && propertyGroup["TargetFramework"].length > 0) {
							targetFramework = propertyGroup["TargetFramework"][propertyGroup["TargetFramework"].length - 1];
						}
						if (propertyGroup["OutputPath"] && propertyGroup["OutputPath"].length > 0) {
							outputPath = propertyGroup["OutputPath"][propertyGroup["OutputPath"].length - 1];
						}
					});

					if (outputType === 'Exe' || outputType === 'WinExe' || sdk === 'Microsoft.NET.Sdk.Web') {
						return {
							name: "netcoredbg Launch",
							request: "launch",
							type: "coreclr",
							program: "${workspaceFolder}/" + `${uri.projectName}` + "/bin/Debug/" + `${targetFramework}` + "/" + `${uri.projectName}.dll`,
							pipeTransport: {
								pipeCwd: "${workspaceFolder}/" + `${uri.projectName}`,
								pipeProgram: "cmd",
								pipeArgs: [
									"/c"
								],
								debuggerPath: "netcoredbg.exe"
							}
						};
					}
				}));
				const configs = items.filter(i => i !== undefined) as vscode.DebugConfiguration[];
				return configs;
			} catch (error: unknown) {
				if (error instanceof Error) {
					vscode.window.showErrorMessage(`DLL选择失败: ${error.message}`);
				} else {
					vscode.window.showErrorMessage(`DLL选择失败: 未知错误`);
				}
				return [];
			}
		}
	}, vscode.DebugConfigurationProviderTriggerKind.Dynamic);

	context.subscriptions.push(netcoredbgConfig);
}

// This method is called when your extension is deactivated
export function deactivate() { }
